const PENDDING = 'PENDDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'

const isPromise = value => {
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    return typeof value.then === 'function'
  }
  return false
}

const resolvePromise = (promise2, x, resolve, reject) => {
  // 处理x的类型 来决定调用
  // 1. 返回了自己 promise2  无法执行
  // 2. x是不是普通值
  if (promise2 === x) {
    return reject(new TypeError('循环调用自己'))
  }
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    let called;  // 默认没有调用成功或者失败  

    try {
      let then = x.then

      if (typeof then === 'function') {
        // 是promise 
        then.call(x, (y) => {
          if (called) return
          called = true
          resolvePromise(promise2, y, resolve, reject)
        }, (r) => {
          if (called) return
          called = true
          reject(r)
        })
      } else {
        resolve(x)
      }
    } catch (error) {
      if (called) return
      called = true
      reject(error)
    }
  } else {
    resolve(x)
  }
}

class Promise {
  static resolve(value) {
    return new Promise((resolve, reject)=>{
      resolve(value)
    })
  }
  static reject(reason) {
    return new Promise((resolve, reject)=>{
      reject(reason)
    })
  }
  
  constructor(executor) {
    this.status = PENDDING
    // 定义两个队列
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = []
    this.value = undefined
    this.reason = undefined
    let resolve = value => {
      if(value instanceof Promise) {
        // 
        return value.then(resolve, reject)
      }
      if (this.status === PENDDING) {
        this.value = value
        this.status = FULFILLED
        this.onResolvedCallbacks.forEach(fn => fn())
      }
    }
    let reject = value => {
      if (this.status === PENDDING) {
        this.reason = value
        this.status = REJECTED
        this.onRejectedCallbacks.forEach(fn => fn())

      }
    }
    // 这边可能会 跑出异常
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }

  // 会判断当前 状态 
  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }

    // 一旦成功或者失败就不能修改
    let promise2 = new Promise((resolve, reject) => {

      if (this.status === FULFILLED) {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value)
            resolvePromise(promise2, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
      }
      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
      }
      if (this.status === PENDDING) {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value)
              resolvePromise(promise2, x, resolve, reject)
            } catch (error) {
              reject(error)
            }
          })

        })
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason)
              resolvePromise(promise2, x, resolve, reject)
            } catch (error) {
              reject(error)
            }
          })
        })
      }
    })
    return promise2
  }
  catch(errCb) {
    return this.then(null, errCb)
  }
  // 转发  将值原封不动的传递
  finally(callback) {
    return this.then((value) => {
        return Promise.resolve(callback()).then(() => {
            return value;
        });
    }, (err) => {
        return Promise.resolve(callback()).then(() => {
            throw err;
        });
    });
  }
  static all(promises) {
    
    return new Promise((resolve,reject)=>{
      let arr = []
      let i = 0
      let processData = (index, data) => {
        arr[index] = data
        if(++i === promises.length) {
          resolve(arr)
        }
      }

      for(let i = o; i < promises.length; i++) {
        let current = promises[i]
        if(isPromise(current)) {
          current.then(data => {
            processData(i, data)
          }, reject)
        }else{
          processData(i, current)
        }
      }
    })
  }
}



Promise.deferred = function () {
  let dfd = {}
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve
    dfd.reject = reject
  })
  return dfd
}

// 测试库 promises-aplus-tests

module.exports = Promise